package com.sina.common.okhttp;

import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.support.constraint.BuildConfig;
import android.text.TextUtils;
import com.sina.common.okhttp.listener.ISupportOkHttp;
import com.sina.common.util.LogUtils;
import com.sina.common.util.SPUtils;
import com.sina.common.util.ToastUtils;
import com.sina.common.value.StaticValue;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.IOException;
import java.net.Proxy;
import java.util.concurrent.TimeUnit;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okhttp3.logging.HttpLoggingInterceptor;

/**
 * OkHttp请求队列
 */
public class OkHttpEnqueue {

    private static final long READ_TIME_OUT = 20 * 1000;

    private static HttpLoggingInterceptor mLogInterceptor = new HttpLoggingInterceptor().setLevel(BuildConfig.DEBUG ? HttpLoggingInterceptor.Level.HEADERS : HttpLoggingInterceptor.Level.NONE);

    public static OkHttpClient mOkHttpClient = getOkHttpClient();

    private static OkHttpClient getOkHttpClient() {
        if(BuildConfig.DEBUG) { // Debug 环境允许使用代理来抓包
            return new OkHttpClient.Builder().addInterceptor(mLogInterceptor).addNetworkInterceptor(mLogInterceptor).connectTimeout(10 * 1000,TimeUnit.MILLISECONDS).writeTimeout(10 * 1000,TimeUnit.MILLISECONDS).readTimeout(READ_TIME_OUT, TimeUnit.MILLISECONDS).build();
        } else {
            return new OkHttpClient.Builder().proxy(Proxy.NO_PROXY).addInterceptor(mLogInterceptor).addNetworkInterceptor(mLogInterceptor).connectTimeout(10 * 1000,TimeUnit.MILLISECONDS).writeTimeout(10 * 1000,TimeUnit.MILLISECONDS).readTimeout(READ_TIME_OUT, TimeUnit.MILLISECONDS).build();
        }
    }

    public static void newCall(String task_name,Request request) {
        newCall(task_name,request, true);
    }

    public static void newCall(String task_name,Request request, boolean needLogin) {
        if (!checkLogin(needLogin)) {
            return;
        }
        newCall(task_name,request, null, needLogin);
    }

    public static void newCall(String task_name,Request request, final ISupportOkHttp okHttpEnqueueListener) {
        newCall(task_name,request, okHttpEnqueueListener, false);
    }

    public static void newCall(String task_name,Request request, final ISupportOkHttp okHttpEnqueueListener, boolean needLogin) {
        if (!checkLogin(needLogin)) {
            if(okHttpEnqueueListener != null) {
                okHttpEnqueueListener.onFailure(task_name,null, null);
            }
            return;
        }
        call(task_name,mOkHttpClient, request, okHttpEnqueueListener, needLogin);
    }

    public static void outTimeCall(String task_name,Request request, long timeout, final ISupportOkHttp okHttpEnqueueListener) {
        outTimeCall(task_name,request, timeout, okHttpEnqueueListener, true);
    }

    public static void outTimeCall(String task_name,Request request, long timeout, final ISupportOkHttp okHttpEnqueueListener, boolean needLogin) {
        if (!checkLogin(needLogin)) {
            if(okHttpEnqueueListener != null) {
                okHttpEnqueueListener.onFailure(task_name,null, null);
            }
            return;
        }
        OkHttpClient.Builder builder = new OkHttpClient.Builder();
        if(!BuildConfig.DEBUG) { // 允许测试环境抓包
            builder = builder.proxy(Proxy.NO_PROXY);
        }
        OkHttpClient okHttpClient = builder.addInterceptor(mLogInterceptor).addNetworkInterceptor(mLogInterceptor).connectTimeout(20 * 1000, TimeUnit.MILLISECONDS).writeTimeout(20 * 1000, TimeUnit.MILLISECONDS).readTimeout(timeout, TimeUnit.MILLISECONDS).build();
        call(task_name,okHttpClient, request, okHttpEnqueueListener, needLogin);
    }

    /**
     * 手动写一个 Request 和 HttpClient 用以在某些特殊情况使用
     */
    public static void call(String task_name,OkHttpClient okHttpClient, Request request, final ISupportOkHttp okHttpEnqueueListener) {
        call(task_name,okHttpClient, request, okHttpEnqueueListener, true);
    }

    public static void call(final String task_name, OkHttpClient okHttpClient, Request request, final ISupportOkHttp okHttpEnqueueListener, boolean needLogin) {
        if (!checkLogin(needLogin)) {
            if(okHttpEnqueueListener != null) {
                okHttpEnqueueListener.onFailure(task_name,null, null);
            }
            return;
        }
        if (okHttpClient == null) {
            okHttpClient = mOkHttpClient;
        }
        okHttpClient.newCall(request).enqueue(new Callback() {

            @Override
            public void onResponse(final Call call, Response response) throws IOException {
                ResponseBody responseBody = response.body();
                if (responseBody != null) {
                    final MediaType mediaType = responseBody.contentType();
                    final byte[] bytes = responseBody.bytes();
                    final String result = new String(bytes);
                    final int code = response.code();
                    LogUtils.d(result);
                    if (okHttpEnqueueListener != null) {
                        new Handler(Looper.getMainLooper()).post(new Runnable() {
                            @Override
                            public void run() {
                                if (code == 200) {
                                    try {
                                        JSONObject jsonObject = new JSONObject(result);
                                        int serverCode = jsonObject.getInt("code");
                                        if (serverCode == NetErrorCode.SUCCESS) {
                                            okHttpEnqueueListener.onSuccess(task_name,call, result, bytes, mediaType);

                                        } else if (serverCode == NetErrorCode.NEED_LOGIN) {

                                            SPUtils.saveObj(StaticValue.getApp(), null, "UserData");
                                            StaticValue.jumpLogin();
                                            okHttpEnqueueListener.onResponse(task_name,call, result, bytes, mediaType);
                                        } else if (serverCode == NetErrorCode.LOAN_STOP) { // 进件系统关闭时不提示用户
                                            okHttpEnqueueListener.onResponse(task_name,call, result, bytes, mediaType);
                                        } else {
                                            if (StaticValue.mShowError) {
                                                netWorkError(jsonObject.getString("message"));
                                            }
                                            okHttpEnqueueListener.onResponse(task_name,call, result, bytes, mediaType);
                                        }
                                    } catch (JSONException e) {
                                        if(result.startsWith("<")) {
                                            netWorkError();
                                            okHttpEnqueueListener.onResponse(task_name,call, result, bytes, mediaType);
                                        }
                                        e.printStackTrace();
                                    }
                                } else {
                                    if (StaticValue.mShowError) {
                                        netWorkError();
                                    }
                                    okHttpEnqueueListener.onResponse(task_name,call, result, bytes, mediaType);
                                }
                            }
                        });
                    }
                }
            }

            @Override
            public void onFailure(final Call call, final IOException e) {
                new Handler(Looper.getMainLooper()).post(new Runnable() {
                    @Override
                    public void run() {
                        if (okHttpEnqueueListener != null) {
                            if (StaticValue.mShowError) {
                                netWorkError();
                            }
                            okHttpEnqueueListener.onFailure(task_name,call, e);
                        }
                    }
                });
            }

        });
    }

    /**
     * 验证是否存在代理
     * @return true 存在，false 不存在
     */
    private static boolean isWifiProxy() {
        final boolean IS_ICS_OR_LATER = Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH;
        String proxyAddress;
        int proxyPort;
        if (IS_ICS_OR_LATER) {
            proxyAddress = System.getProperty("http.proxyHost");
            String portStr = System.getProperty("http.proxyPort");
            proxyPort = Integer.parseInt((portStr != null ? portStr : "-1"));
        } else {
            proxyAddress = android.net.Proxy.getHost(StaticValue.getApp());
            proxyPort = android.net.Proxy.getPort(StaticValue.getApp());
        }
        return (!TextUtils.isEmpty(proxyAddress)) && (proxyPort != -1);
    }

    /**
     * 某些接口  用户未登录则不再请求
     * @param needLogin 是否需要登录
     * @return true：已登录或者不需要登录； false：需要登录但是未登录
     */
    private static boolean checkLogin(boolean needLogin) {
        if (!needLogin) {
            return true;
        } else {
            return StaticValue.isLogin();
        }
    }

    private static void netWorkError() {
        netWorkError("网络请求异常，请重试！");
    }

    private static void netWorkError(String error) {
        if (error != null && !error.equals("null")) {
            ToastUtils.showToast(error);
        } else {
            netWorkError();
        }
    }

}
